package com.smzd.utils.quartz;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzHelper {
	private static QuartzHelper instance;

	private Scheduler scheduler;

	private QuartzHelper() throws SchedulerException {
		scheduler = StdSchedulerFactory.getDefaultScheduler();
		scheduler.start();

	}

	private static synchronized QuartzHelper getInstance() {
		if (instance == null) {
			try {
				instance = new QuartzHelper();
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
		if (instance != null) {
			try {
				if (!instance.scheduler.isStarted()) {
					instance = new QuartzHelper();
				}
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
		return instance;
	}

	public static void delegate(IQuartzJobDetailDelegater delegater) {
		QuartzHelper instance = getInstance();
		if (instance != null && delegater != null) {
			try {
				delegater.delegateJobDetail(instance.scheduler);
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
	}

	public static void shutdown() {
		QuartzHelper instance = getInstance();
		if (instance != null) {
			try {
				if (!instance.scheduler.isShutdown()) {
					instance.scheduler.shutdown();
				}
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
	}

	public <T extends Job> JobDetail newJobDetail(Class<T> clazz, String name) {
		return newJobDetail(clazz, name, null, null);
	}

	public <T extends Job> JobDetail newJobDetail(Class<T> clazz, String name,
			Map<String, Object> data) {
		return newJobDetail(clazz, name, null, data);
	}

	public <T extends Job> JobDetail newJobDetail(Class<T> clazz, String name,
			String group) {
		return newJobDetail(clazz, name, group, null);
	}

	public <T extends Job> JobDetail newJobDetail(Class<T> clazz, String name,
			String group, Map<String, Object> data) {
		JobBuilder jobBuilder = JobBuilder.newJob(clazz).withIdentity(name,
				group);
		if (data != null) {
			JobDataMap map = new JobDataMap();
			map.putAll(data);
			jobBuilder.usingJobData(map);
		}
		return jobBuilder.build();
	}

	public static MyTrigger newSimpleTrigger(Date date) {
		return newSimpleTrigger(date, null, null, null);
	}

	public static MyTrigger newSimpleTrigger(Date date, Map<String, Object> data) {
		return newSimpleTrigger(date, null, null, data);
	}

	public static MyTrigger newSimpleTrigger(Date date, String name) {
		return newSimpleTrigger(date, name, null, null);
	}

	public static MyTrigger newSimpleTrigger(Date date, String name,
			Map<String, Object> data) {
		return newSimpleTrigger(date, name, null, data);
	}

	public static MyTrigger newSimpleTrigger(Date date, String name,
			String group) {
		return newSimpleTrigger(date, name, group, null);
	}

	public static MyTrigger newSimpleTrigger(Date date, String name,
			String group, Map<String, Object> data) {
		MySimpleTrigger trigger = new MySimpleTrigger();
		trigger.setExecuteDate(date);
		trigger.setName(name);
		trigger.setGroup(group);
		trigger.setData(data);
		return trigger;
	}
	private static Trigger newSimpleTrigger(MySimpleTrigger myTrigger) {
		TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
		if (myTrigger.getExecuteDate() != null) {
			triggerBuilder.startAt(myTrigger.getExecuteDate());
		} else {
			triggerBuilder.startNow();
		}
		return getCommonTrigger(myTrigger, triggerBuilder);
	}

	public static MyCronTrigger newCronTrigger(String cron) {
		return newCronTrigger(cron, null, null, null);
	}

	public static MyCronTrigger newCronTrigger(String cron, Map<String, Object> data) {
		return newCronTrigger(cron, null, null, data);
	}

	public static MyCronTrigger newCronTrigger(String cron, String name) {
		return newCronTrigger(cron, name, null, null);
	}

	public static MyCronTrigger newCronTrigger(String cron, String name,
			Map<String, Object> data) {
		return newCronTrigger(cron, name, null, data);
	}

	public static MyCronTrigger newCronTrigger(String cron, String name,
			String group) {
		return newCronTrigger(cron, name, group, null);
	}

	public static MyCronTrigger newCronTrigger(String cron, String name,
			String group, Map<String, Object> data) {
		MyCronTrigger trigger = new MyCronTrigger();
		trigger.setCronExpression(cron);
		trigger.setName(name);
		trigger.setGroup(group);
		trigger.setData(data);
		return trigger;
	}

	private static Trigger newCronTrigger(MyCronTrigger myTrigger) {
		TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
		if(myTrigger.getName()==null){
			myTrigger.setName(UUID.randomUUID().toString());
		}
		triggerBuilder.withIdentity(myTrigger.getName(), myTrigger.getGroup());
		if (myTrigger.getCronExpression() != null) {
			CronScheduleBuilder scheduleBilder = CronScheduleBuilder
					.cronSchedule(myTrigger.getCronExpression());
			triggerBuilder.withSchedule(scheduleBilder);
		} else {
			triggerBuilder.startNow();
		}
		return getCommonTrigger(myTrigger, triggerBuilder);
	}

	private static Trigger getCommonTrigger(MyTrigger myTrigger, TriggerBuilder<Trigger> triggerBuilder) {
		String jobName = myTrigger.getJobName();
		String jobGroup = myTrigger.getJobGroup();
		Map<String, Object> data = myTrigger.getData();
		if (jobName != null) {
			triggerBuilder.forJob(jobName, jobGroup);
		}
		if (data != null) {
			JobDataMap map = new JobDataMap();
			map.putAll(data);
			triggerBuilder.usingJobData(map);
		}
		Trigger trigger = triggerBuilder.build();
		return trigger;
	}
	
	public static Trigger buildTrigger(MyTrigger myTrigger){
		Trigger trigger;
		if(myTrigger instanceof MySimpleTrigger){
			trigger = newSimpleTrigger((MySimpleTrigger)myTrigger);
		}else
		if(myTrigger instanceof MyCronTrigger){
			trigger = newCronTrigger((MyCronTrigger)myTrigger);
		}else{
			trigger = null;
		}
		return trigger;
	}

	public static void delegateJobDetail(Trigger trigger, JobDetail job)
			throws SchedulerException {
		QuartzHelper instance = getInstance();
		if (instance != null) {
			if (job == null) {
				instance.scheduler.scheduleJob(trigger);
			} else {
				JobKey key = trigger.getJobKey();
				if (key == null) {
					instance.scheduler.scheduleJob(job, trigger);
				} else {
					JobDetail job1 = instance.scheduler.getJobDetail(key);
					if (job1 != null && job1.equals(job)) {
						instance.scheduler.scheduleJob(trigger);
					} else {
						instance.scheduler.scheduleJob(job, trigger);
					}
				}
			}
		}

	}

	public static JobDetail newJob(Class<? extends Job> clazz) {
		return newJob(clazz, null, null, null);
	}

	public static JobDetail newJob(Class<? extends Job> clazz,
			Map<String, Object> data) {
		return newJob(clazz, null, null, data);
	}

	public static JobDetail newJob(Class<? extends Job> clazz, String name) {
		return newJob(clazz, name, null, null);
	}

	public static JobDetail newJob(Class<? extends Job> clazz, String name,
			Map<String, Object> data) {
		return newJob(clazz, name, null, data);
	}

	public static JobDetail newJob(Class<? extends Job> clazz, String name,
			String group) {
		return newJob(clazz, name, group, null);
	}

	public static JobDetail newJob(Class<? extends Job> clazz, String name,
			String group, Map<String, Object> data) {
		if (name == null || name.length() == 0) {
			name = UUID.randomUUID().toString();
		}
		JobBuilder builder = JobBuilder.newJob(clazz).withIdentity(name, group);
		if (data != null && data.size() > 0) {
			builder.usingJobData(new JobDataMap(data));
		}
		return builder.build();
	}

	public static void delegateJobDetail(Trigger trigger)
			throws SchedulerException {
		delegateJobDetail(trigger, null);
	}
}